#include "core_command.h"
#include "../mem/mem_manager.h"
#include "../common/console.h"

#define TYPE_NONE	0
#define TYPE_FUNC	1
#define TYPE_ALIAS	2

typedef struct _ttreenode
{
	int type;
	union
	{
		void (*asFunc)();
		char *asStr;
	}ptr;
	int childCount;
	_ttreenode *child[40];
}TTreeNode;

static TTreeNode *root;
int nodeCount = 0;

//maps chars to ?ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+-
static int mapPathChar(char c)
{
	if ((c>='a')&&(c<='z'))
		return 1 + (c-'a');
	if ((c>='A')&&(c<='Z'))
		return 1 + (c-'A');
	if ((c>='0')&&(c<='9'))
		return 27 + (c-'0') ;

	if (c=='_')
		return 37;
	if (c=='+')
		return 38;
	if (c=='-')
		return 39;
	
	return 0;
}

static TTreeNode* createNode()
{
	TTreeNode *node;

	g_allocs(node, TTreeNode);
	node->type = TYPE_NONE;
	node->ptr.asFunc = NULL;
	node->childCount = 0;

	for (int i=0;i<40;i++)
		node->child[i] = NULL;

	con_printf("Node %d created\n",++nodeCount);
	return node;
}

static TTreeNode* findPath(TTreeNode *node, const char* name)
{
	if ((name == NULL)||(node==NULL))
		return NULL;

	if (name[0] == 0)
		return node;

	return findPath(node->child[mapPathChar(name[0])], name+1);
}

static TTreeNode* createPath(TTreeNode *node, const char* name)
{
	if ((name == NULL)||(node==NULL))
		return NULL;

	if (name[0] == 0)
		return node;

	int p = mapPathChar(name[0]);

	if (node->child[p] == NULL)
	{
		node->child[p] = createNode();
		node->childCount++;
	}
	
	return createPath(node->child[p], name+1);
}

void cmd_initCommands()
{
	root = createNode();
}

void cmd_addCommand(const char* name, void (*funcPtr)())
{
	TTreeNode *node = createPath(root, name);
	node->ptr.asFunc = funcPtr;
	node->type = TYPE_FUNC;
}

void cmd_addCommand(const char* name, const char* func)
{
	TTreeNode *node = createPath(root, name);
	g_strdup(node->ptr.asStr, func);
	node->type = TYPE_ALIAS;
}

void testCommands()
{
	cmd_initCommands();

	cmd_addCommand("god", "1");
	cmd_addCommand("give", "1");
	cmd_addCommand("map", "1");
	cmd_addCommand("+attack", "1");
	cmd_addCommand("+back", "1");
	cmd_addCommand("+button0", "1");
	cmd_addCommand("+button1", "1");
	cmd_addCommand("+button2", "1");
	cmd_addCommand("+button3", "1");
	cmd_addCommand("+button4", "1");
	cmd_addCommand("+button5", "1");
	cmd_addCommand("+button6", "1");
	cmd_addCommand("-button0", "1");
	cmd_addCommand("-button1", "1");
	cmd_addCommand("-button2", "1");
	cmd_addCommand("-button3", "1");
	cmd_addCommand("-button4", "1");
	cmd_addCommand("-button5", "1");
	cmd_addCommand("-button6", "1");
	cmd_addCommand("+forward", "1");
	cmd_addCommand("+left", "1");
	cmd_addCommand("+lookdown", "1");
	cmd_addCommand("+lookup", "1");
	cmd_addCommand("+mlook", "1");
	cmd_addCommand("+movedown", "1");
	cmd_addCommand("+moveleft", "1");
	cmd_addCommand("+moveright", "1");
	cmd_addCommand("+moveup", "1");
	cmd_addCommand("+right", "1");
	cmd_addCommand("+speed", "1");
	cmd_addCommand("+strafe", "1");
	cmd_addCommand("-attack", "1");
	cmd_addCommand("-back", "1");
	cmd_addCommand("-forward", "1");
	cmd_addCommand("-left", "1");
	cmd_addCommand("-lookdown", "1");
	cmd_addCommand("-lookup", "1");
	cmd_addCommand("-mlook", "1");
	cmd_addCommand("-movedown", "1");
	cmd_addCommand("-moveleft", "1");
	cmd_addCommand("-moveright", "1");
	cmd_addCommand("-moveup", "1");
	cmd_addCommand("-right", "1");
	cmd_addCommand("-speed", "1");
	cmd_addCommand("-strafe", "1");
	cmd_addCommand("bind", "1");
	cmd_addCommand("bindlist", "1");
	cmd_addCommand("centerview", "1");
	cmd_addCommand("joy_advancedupdate", "1");
	cmd_addCommand("messagemode", "1");
	cmd_addCommand("messagemode2", "1");
	cmd_addCommand("toggle", "1");
	cmd_addCommand("toggleconsole", "1");
	cmd_addCommand("unbind", "1");
	cmd_addCommand("unbindall", "1");
	cmd_addCommand("imagelist", "1");
	cmd_addCommand("midiinfo", "1");
	cmd_addCommand("modelist", "1");
	cmd_addCommand("modellist", "1");
	cmd_addCommand("scanservers", "1");
	cmd_addCommand("sectorlist", "1");
	cmd_addCommand("serverinfo", "1");
	cmd_addCommand("shaderlist", "1");
	cmd_addCommand("skinlist", "1");
	cmd_addCommand("soundinfo", "1");
	cmd_addCommand("soundlist", "1");
	cmd_addCommand("status", "1");
	cmd_addCommand("systeminfo", "1");
	cmd_addCommand("userinfo", "1");
	cmd_addCommand("vmtest", "1");
	cmd_addCommand("z_stats", "1");
	cmd_addCommand("music", "1");
	cmd_addCommand("play", "1");
	cmd_addCommand("snd_restart", "1");
	cmd_addCommand("stopsound", "1");
	cmd_addCommand("record", "1");
	cmd_addCommand("stopdemo", "1");
	cmd_addCommand("demo", "1");
	cmd_addCommand("serverrecord", "1");
	cmd_addCommand("serverstop", "1");
	cmd_addCommand("connect", "1");
	cmd_addCommand("kick", "1");
	cmd_addCommand("serverlist", "1");
	cmd_addCommand("disconnect", "1");
	cmd_addCommand("heartbeat", "1");
	cmd_addCommand("devmap", "1");
	cmd_addCommand("cg_thirdperson", "1");
	cmd_addCommand("arena", "1");
	cmd_addCommand("changeVectors", "1");
	cmd_addCommand("cinematic", "1");
	cmd_addCommand("clear", "1");
	cmd_addCommand("cmd", "1");
	cmd_addCommand("condump", "1");
	cmd_addCommand("configstrings", "1");
	cmd_addCommand("crash", "1");
	cmd_addCommand("cvar_restart", "1");
	cmd_addCommand("dir", "1");
	cmd_addCommand("dumpuser", "1");
	cmd_addCommand("echo", "1");
	cmd_addCommand("error", "1");
	cmd_addCommand("exec", "1");
	cmd_addCommand("freeze", "1");
	cmd_addCommand("gfxinfo", "1");
	cmd_addCommand("hunk_stats", "1");
	cmd_addCommand("in_restart", "1");
	cmd_addCommand("map", "1");
	cmd_addCommand("path", "1");
	cmd_addCommand("quit", "1");
	cmd_addCommand("rcon", "1");
	cmd_addCommand("restart", "1");
	cmd_addCommand("say", "1");
	cmd_addCommand("screenshot", "1");
	cmd_addCommand("set", "1");
	cmd_addCommand("seta", "1");
	cmd_addCommand("setenv", "1");
	cmd_addCommand("sets", "1");
	cmd_addCommand("setu", "1");
	cmd_addCommand("testfog", "1");
	cmd_addCommand("testshader", "1");
	cmd_addCommand("touchFile", "1");
	cmd_addCommand("vid_restart", "1");
	cmd_addCommand("vstr", "1");
	cmd_addCommand("wait", "1");



	con_printf("ocupa %d\n",nodeCount * sizeof(TTreeNode));
/*	TTreeNode *node = findPath(root, "baluba");
	con_printf("Found: %s\n",node->ptr.asStr);*/
}